/**
 * @file iterator_example.cpp
 * @brief Demonstrates iterator usage and traversal operations
 */

#include "../complete_binary_tree.hpp"
#include <iostream>
#include <algorithm>
#include <numeric>

int main() {
    std::cout << "=== Complete Binary Tree - Iterator Example ===\n\n";

    // Create a tree with numeric types
    CompleteBinaryTree<double, int> tree(10);
    
    // Initialize using iterators
    std::cout << "=== Initialization ===\n";
    
    // Fill leaves with sequence
    std::iota(tree.leaf_begin(), tree.leaf_end(), 1.0);
    std::cout << "Initialized " << tree.leaf_count() << " leaves with sequence [1.0, 10.0]\n";
    
    // Fill internal nodes with sequence
    std::iota(tree.internal_begin(), tree.internal_end(), 100);
    std::cout << "Initialized " << tree.internal_count() << " internal nodes starting from 100\n";

    // Iterate over leaves
    std::cout << "\n=== Forward Leaf Iteration ===\n";
    std::cout << "Leaves: ";
    for (auto it = tree.leaf_begin(); it != tree.leaf_end(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << "\n";

    // Range-based for loop using iterators
    std::cout << "\n=== Range-Based Iteration ===\n";
    std::cout << "Doubling all leaf values...\n";
    for (auto it = tree.leaf_begin(); it != tree.leaf_end(); ++it) {
        *it *= 2;
    }
    
    std::cout << "New leaves: ";
    for (auto it = tree.leaf_begin(); it != tree.leaf_end(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << "\n";

    // Reverse iteration
    std::cout << "\n=== Reverse Leaf Iteration ===\n";
    std::cout << "Leaves (reversed): ";
    for (auto it = tree.leaf_rbegin(); it != tree.leaf_rend(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << "\n";

    // Internal node iteration
    std::cout << "\n=== Internal Node Iteration ===\n";
    std::cout << "Internal nodes: ";
    for (auto it = tree.internal_begin(); it != tree.internal_end(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << "\n";

    // Const iterators
    std::cout << "\n=== Const Iteration ===\n";
    const auto& const_tree = tree;
    std::cout << "Const leaves: ";
    for (auto it = const_tree.leaf_cbegin(); it != const_tree.leaf_cend(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << "\n";

    // STL algorithms
    std::cout << "\n=== STL Algorithms ===\n";
    
    // Find maximum leaf
    auto max_leaf = std::max_element(tree.leaf_begin(), tree.leaf_end());
    std::cout << "Maximum leaf value: " << *max_leaf << "\n";
    
    // Count leaves greater than 10
    auto count = std::count_if(tree.leaf_begin(), tree.leaf_end(),
                                [](double x) { return x > 10.0; });
    std::cout << "Leaves > 10.0: " << count << "\n";
    
    // Sum of all leaves
    auto sum = std::accumulate(tree.leaf_begin(), tree.leaf_end(), 0.0);
    std::cout << "Sum of leaves: " << sum << "\n";

    // Transform leaves
    std::cout << "\n=== Transform Operation ===\n";
    std::transform(tree.leaf_begin(), tree.leaf_end(), tree.leaf_begin(),
                   [](double x) { return x / 2.0; });
    std::cout << "Halved leaves: ";
    for (auto it = tree.leaf_begin(); it != tree.leaf_end(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << "\n";

    // for_each_leaf method
    std::cout << "\n=== for_each_leaf Method ===\n";
    std::cout << "Applying lambda to each leaf...\n";
    tree.for_each_leaf([](double& x) {
        x = x * x;  // Square each value
    });
    
    std::cout << "Squared leaves: ";
    for (auto it = tree.leaf_begin(); it != tree.leaf_end(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << "\n";

    // for_each_internal method
    std::cout << "\n=== for_each_internal Method ===\n";
    std::cout << "Incrementing all internal nodes...\n";
    tree.for_each_internal([](int& x) {
        x += 10;
    });
    
    std::cout << "Updated internal nodes: ";
    for (auto it = tree.internal_begin(); it != tree.internal_end(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << "\n";

    // Reverse internal iteration
    std::cout << "\n=== Reverse Internal Iteration ===\n";
    std::cout << "Internal nodes (reversed): ";
    for (auto it = tree.internal_rbegin(); it != tree.internal_rend(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << "\n";

    std::cout << "\n=== Example Complete ===\n";
    return 0;
}
